package org.opens.interceptor;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.opens.aop.aspect.Token;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.UUID;

@Slf4j
public class TokenInterceptor extends HandlerInterceptorAdapter {

    public final static String TOKEN = "token";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            Method method = ((HandlerMethod) handler).getMethod();
            Token token = method.getAnnotation(Token.class);
            if (token != null) {
                HttpSession session = request.getSession();
                boolean generate = token.generate();
                if (generate) {
                    String tokenUUID = UUID.randomUUID().toString();
                    session.setAttribute(TOKEN, tokenUUID);
                    log.info("token: " + tokenUUID + "已建立");
                    return true;
                }

                boolean remove = token.remove();
                if (remove) {
                    if (isRepeatCommit(request)) {
                        log.warn("表单重复提交:" + request.getRequestURL());
                        return false;
                    }
                    log.info("token: " + session.getAttribute(TOKEN) + "已删除");
                    session.removeAttribute(TOKEN);
                }
            }
            return true;
        }
        return super.preHandle(request, response, handler);
    }

    private boolean isRepeatCommit(HttpServletRequest request) {
        Assert.notNull(request, "request对象不能为空");
        String sessionToken = (String) request.getSession().getAttribute(TOKEN);
        if (StrUtil.isEmpty(sessionToken)) {
            return true;
        }

        String reqToken = request.getHeader(TOKEN);
        if (StrUtil.isEmpty(reqToken)) {
            reqToken = request.getParameter(TOKEN);
            if (StrUtil.isEmpty(reqToken)) {
                return true;
            }
        }

        if (!reqToken.equals(sessionToken)) {
            return true;
        }

        return false;
    }
}
